############################################################################
# Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         #
# Martin Renou                                                             #
# Copyright (c) QuantStack                                                 #
# Copyright (c) Serge Guelton                                              #
#                                                                          #
# Distributed under the terms of the BSD 3-Clause License.                 #
#                                                                          #
# The full license is in the file LICENSE, distributed with this software. #
############################################################################

cmake_minimum_required(VERSION 3.15)
project(ksimd)
option(KSIMD_REFACTORING ON)

set(KSIMD_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

# Versioning
# ==========
file(STRINGS "${KSIMD_INCLUDE_DIR}/ksimd/config/ksimd_config.hpp" ksimd_version_defines
     REGEX "#define KSIMD_VERSION_(MAJOR|MINOR|PATCH)")
foreach(ver ${ksimd_version_defines})
    if(ver MATCHES "#define KSIMD_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
        set(KSIMD_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
    endif()
endforeach()
set(${PROJECT_NAME}_VERSION
    ${KSIMD_VERSION_MAJOR}.${KSIMD_VERSION_MINOR}.${KSIMD_VERSION_PATCH})
message(STATUS "ksimd v${${PROJECT_NAME}_VERSION}")

# Build
# =====

set(KSIMD_HEADERS
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_constants.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_fma3_avx.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_fma3_avx2.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_fma3_sse.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_fma4.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_generic.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_isa.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_neon.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_neon64.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_scalar.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_sse2.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_sse3.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_sse4_1.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_sse4_2.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_ssse3.hpp
${KSIMD_INCLUDE_DIR}/ksimd/arch/ksimd_sve.hpp
${KSIMD_INCLUDE_DIR}/ksimd/config/ksimd_arch.hpp
${KSIMD_INCLUDE_DIR}/ksimd/config/ksimd_config.hpp
${KSIMD_INCLUDE_DIR}/ksimd/config/ksimd_cpuid.hpp
${KSIMD_INCLUDE_DIR}/ksimd/memory/ksimd_aligned_allocator.hpp
${KSIMD_INCLUDE_DIR}/ksimd/memory/ksimd_alignment.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_all_registers.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_api.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_neon_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_neon64_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_avx2_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_avx512f_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_avx_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_batch.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_batch_constant.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_fma3_avx_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_fma3_avx2_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_fma3_sse_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_fma4_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_generic_arch.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_sse2_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_sse3_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_sse4_1_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_sse4_2_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_ssse3_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_sve_register.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_traits.hpp
${KSIMD_INCLUDE_DIR}/ksimd/types/ksimd_utils.hpp
${KSIMD_INCLUDE_DIR}/ksimd/ksimd.hpp
)

add_library(ksimd INTERFACE)

target_include_directories(ksimd INTERFACE
    $<BUILD_INTERFACE:${KSIMD_INCLUDE_DIR}>
    $<INSTALL_INTERFACE:include>)

if (ENABLE_XTL_COMPLEX)
    target_compile_features(ksimd INTERFACE cxx_std_14)
else()
    target_compile_features(ksimd INTERFACE cxx_std_11)
endif()

OPTION(ENABLE_XTL_COMPLEX "enables support for xcomplex defined in xtl" OFF)
OPTION(BUILD_TESTS "ksimd test suite" OFF)

if(ENABLE_XTL_COMPLEX)
    add_definitions(-DKSIMD_ENABLE_XTL_COMPLEX=1)
    find_package(xtl 0.7.0 REQUIRED)
    target_link_libraries(ksimd INTERFACE xtl)
endif()

if(BUILD_TESTS)
    enable_testing()
    add_subdirectory(test)
endif()

OPTION(BUILD_BENCHMARK "ksimd benchmarks" OFF)
if(BUILD_BENCHMARK)
    add_subdirectory(benchmark)
endif()

OPTION(BUILD_EXAMPLES "ksimd examples" OFF)
if(BUILD_EXAMPLES)
    add_subdirectory(examples)
endif()

# Installation
# ============

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(JoinPaths)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

include(check_target_intrinsic)

install(TARGETS ksimd
        EXPORT ${PROJECT_NAME}-targets)

# Makes the project importable from the build directory
export(EXPORT ${PROJECT_NAME}-targets
       FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")

install(DIRECTORY ${KSIMD_INCLUDE_DIR}/ksimd
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# GNUInstallDirs "DATADIR" wrong here; CMake search path wants "share".
set(KSIMD_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for ksimdConfig.cmake")

configure_package_config_file(${PROJECT_NAME}Config.cmake.in
                              "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
                              INSTALL_DESTINATION ${KSIMD_CMAKECONFIG_INSTALL_DIR})

# ksimd is header-only and does not depend on the architecture.
# Remove CMAKE_SIZEOF_VOID_P from xtensorConfigVersion.cmake so that an xtensorConfig.cmake
# generated for a 64 bit target can be used for 32 bit targets and vice versa.
set(_XTENSOR_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
unset(CMAKE_SIZEOF_VOID_P)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
                                 VERSION ${${PROJECT_NAME}_VERSION}
                                 COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
              ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_target_intrinsic.cmake
        DESTINATION ${KSIMD_CMAKECONFIG_INSTALL_DIR})
install(EXPORT ${PROJECT_NAME}-targets
        FILE ${PROJECT_NAME}Targets.cmake
        DESTINATION ${KSIMD_CMAKECONFIG_INSTALL_DIR})

join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file(${PROJECT_NAME}.pc.in
               "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
                @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
        DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
